package fst.calculi.STLC

// version of Solution for STLC, your version should reside in the `fst` package!
object Solution extends fst.Tester {
  // this style of composing components is described in http://lamp.epfl.ch/~odersky/papers/ScalableComponent.pdf
  object mySyntax extends Substitution
  object myParser extends Parsing {val syntax = mySyntax} 
  object myEval extends Evaluation {val syntax = mySyntax} 
  object myTyper extends Typers {val syntax = mySyntax} 
  
  type Node = mySyntax.Node
  type Type = mySyntax.Type
  type Term = mySyntax.Term
  
  // delegate to appropriate methods in your package:
  def parse(expr: String): Option[Term] 
    = myParser.parse(expr) match {
        case myParser.Success(x, _) => Some(x) 
        case ns: myParser.NoSuccess => println(ns.errorInfo); None
      }
      
  def typeOf(expr: Term): Option[Type] = myTyper.typeOf(expr) match {
    case myTyper.Success(x, _) => Some(x) 
    case ns: myTyper.NoSuccess => println(ns.errorInfo); None
  }
  
  def eval(expr: Term): Option[Term]  = Some(myEval.evalX(expr))

  def prettyPrint(n: Node): String = n.prettyPrint
  
  // well, in this case, the identity function really :-)
  val reverse = 
"""
(\x: Bool. x)
"""
}

// example test
object SimpleTest extends Application {
  import Solution._

  for(src <- Some(reverse);
      prog <- parse(src+" true");
      tp <- typeOf(prog);
      result <- eval(prog)) println(prettyPrint(result)+" : "+prettyPrint(tp))
}